package com.sunray.cmd;

//import org.opencv.core.Mat;
//import org.opencv.imgcodecs.Imgcodecs;
//import org.opencv.objdetect.QRCodeDetector;


import com.google.zxing.NotFoundException;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import org.opencv.core.CvType;

import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class MatUtil {

    public static void main(String[] args) {
        File file=new File("D:\\home\\caixq\\desktop\\tmp\\Rotated_Undecoded");
        Map<String,String> result=new HashMap<>();

        new File(file.getAbsolutePath()+File.separator+"point").mkdirs();
        new File(file.getAbsolutePath()+File.separator+"result").mkdirs();
        for (File f : file.listFiles()) {
            if(f.isDirectory())continue;
            String s=f.getAbsolutePath();
            String path = newImg(s, 20, 0, 0, 256, 256);
            try {
                String value = ZxingUtil.decode(new FileInputStream(path));
                result.put(new File(path).getName(),value);
            } catch (Exception e) {
                e.printStackTrace();
                result.put(new File(path).getName(),"");
            }
        }
        for (String s : result.keySet()) {
            System.out.println(s+"\t"+result.get(s));
        }
    }
    public static String  newImg(String filePath,int dataMatrixSize,int startX,int startY,int contentWidth,int contentHeight){
        File file=new File(filePath);

        // 加载图像
        Mat image = opencv_imgcodecs.imread(file.getAbsolutePath());

        Mat grayImage = new Mat();

        // 将彩色图像转换为灰度图像
        opencv_imgproc.cvtColor(image, grayImage, opencv_imgproc.COLOR_BGR2GRAY);
        opencv_imgproc.adaptiveThreshold(grayImage, grayImage, 255, opencv_imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, opencv_imgproc.THRESH_BINARY, 81, 2);

        BytePointer ptr;
        Map<Integer, Map<String,Integer>> pointMap = new java.util.HashMap<>();


        int sum=0;
        int count=0;

        for (int y = 0; y < grayImage.rows(); y++) {
            ptr = grayImage.ptr(y);
            for (int x = 0; x < grayImage.cols(); x++) {
                if(y<startY||y>startY+contentHeight||x<startX||x>startX+contentWidth) {
                    ptr.put(x, (byte) 255); // 设置新的像素值
                    continue;
                }
                int vy=(y-startY)*dataMatrixSize%contentHeight;
                int vx=(x-startX)*dataMatrixSize%contentWidth;
                if(!(vy>=contentHeight/9&&vy<contentHeight*8/9&&vx>=contentWidth/9&&vx<contentWidth*8/9)) {
                    ptr.put(x, (byte) 200); // 设置新的像素值
                    continue;
                }
                // 获取当前像素的灰度值
                byte pixelValue = ptr.get(x); // 从指针处获取字节值

                int key=(y-startY)* dataMatrixSize/contentHeight *dataMatrixSize  + (x-startX)*dataMatrixSize/contentWidth;

                Map<String,Integer> integers=pointMap.getOrDefault(key,new HashMap<>());
                int value=pixelValue>=0?pixelValue:(256+pixelValue);
                String mapKey=((y-startY)* dataMatrixSize%contentHeight)/dataMatrixSize+":"+((x-startX)*dataMatrixSize%contentWidth)/dataMatrixSize;
                if((y-startY)* dataMatrixSize/contentHeight == 0){
                    sum+=value;
                    count++;
                }
                integers.put(mapKey,value);
                pointMap.put(key,integers);

            }
            // 移动到下一行的开始位置
        }
        int threshold=sum/count;
        System.out.println(threshold);

        opencv_imgcodecs.imwrite(file.getParent()+File.separator+"point/"+file.getName(), grayImage);

        Map<Integer,Byte> values=getValues(pointMap,threshold);

        int num=15;
        Mat result =Mat.zeros((dataMatrixSize+2)*num, (dataMatrixSize+2)*num, CvType.CV_8UC1).asMat();
        for (int i = 0; i < (dataMatrixSize+2)*num; i++) {
            ptr = result.ptr(i);
            for (int j = 0; j < (dataMatrixSize+2)*num; j++) {
                if(i/num==0||j/num==0||i/num==dataMatrixSize+1||j/num==dataMatrixSize+1){
                    ptr.put(j, (byte) 255);
                    continue;
                }

                int key=(i/num-1)*dataMatrixSize+j/num-1;
                if(values.get(key)!=null)
                    ptr.put(j,values.get(key));
            }
        }



        String fileName=file.getParent()+File.separator+"result/"+file.getName();
        // 保存修改后的灰度图像
        opencv_imgcodecs.imwrite(fileName, result);
        return fileName;
    }

    private static Map<Integer, Byte> getValues(Map<Integer, Map<String, Integer>> pointMap, int threshold) {
        Map<Integer, Byte> result=new HashMap<>();
        for (Map.Entry<Integer, Map<String, Integer>> integerMapEntry : pointMap.entrySet()) {
            result.put(integerMapEntry.getKey(), getContentValue(integerMapEntry.getValue(),threshold));
        }

        return result;
    }

    private static byte getContentValue(Map<String, Integer> integers, int threshold) {
        String type="0";

        List<Integer> xs=new ArrayList<>();
        List<Integer> ys=new ArrayList<>();
        for (String s : integers.keySet()) {
            xs.add(Integer.parseInt(s.split(":")[1]));
            ys.add(Integer.parseInt(s.split(":")[0]));
        }
        int maxX=xs.stream().mapToInt(Integer::intValue).max().getAsInt();
        int maxY=ys.stream().mapToInt(Integer::intValue).max().getAsInt();
        int sum=0;
        int sumNum=0;
        for (String s : integers.keySet()) {
            int x=Integer.parseInt(s.split(":")[1]);
            int y=Integer.parseInt(s.split(":")[0]);
            int num=Math.min(x,maxX-x)*Math.min(y,maxY-y);
//            num*=num;
//            num*=num;
            num=1;
            sumNum+=num;
            sum+=num*integers.get(s);
        }
        int result=sum/sumNum;
        switch (type){
            case "0":
                return (byte)(result<threshold?0:255);
//                return (byte)(result);
        }

        return 0;
    }

    private static BufferedImage convertMatToBufferedImage(Mat mat) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (mat.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        BufferedImage image = new BufferedImage(mat.arrayWidth(), mat.arrayHeight(), type);
        WritableRaster raster = image.getRaster();
        DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
        byte[] data = dataBuffer.getData();
        mat.getByteBuffer().get(data);
        return image;
    }
}
